#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>

#include <QQueue>
#include <QWriteLocker>
#include <QTimer>

#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QSqlRecord>
#include <QtDebug>

#include <QDateTime>

QQueue<T_MSG> g_cQueue;
QReadWriteLock g_cRWLock;
QSqlDatabase g_cDB;
QTimer  g_cTime;


bool WriteQueue(T_MSG *tMsg)
{
    if (NULL == tMsg)
    {
        return false;
    }

    g_cRWLock.lockForWrite();
    g_cQueue.enqueue(*tMsg);
    g_cRWLock.unlock();

    return true;
}

int CallBackICP(void *p)
{
    if (NULL == p)
    {
        return -1;
    }

    T_BDICPDATA tData = *(T_BDICPDATA*)p;
    memset(&tData, 0x00, sizeof(tData));
    memcpy(&tData, p, sizeof(tData));

    qDebug() << QString("ICP UserID[%1] UserFlag[%2]").arg(tData.uUserID).arg(tData.eUserFlag);

    T_MSG tMsg;
    tMsg.eType = E_MSGTYPE_ICP;
    tMsg.pMsg = new T_BDICPDATA;
    memset(tMsg.pMsg, 0x00, sizeof(T_BDICPDATA));
    memcpy(tMsg.pMsg, p, sizeof(T_BDICPDATA));

    WriteQueue(&tMsg);

    return 0;
}
int CallBackTCI(void *p)
{
    if (NULL == p)
    {
        return -1;
    }

    T_BDTCIDATA tData;
    memset(&tData, 0x00, sizeof(tData));
    memcpy(&tData, p, sizeof(tData));

    qDebug() << QString("TCI SrcID[%1] Msg[%2]").arg(tData.uSrcID).arg(tData.sMsg);

    T_MSG tMsg;
    tMsg.eType = E_MSGTYPE_TCI;
    tMsg.pMsg = new T_BDTCIDATA;
    memset(tMsg.pMsg, 0x00, sizeof(T_BDTCIDATA));
    memcpy(tMsg.pMsg, p, sizeof(T_BDTCIDATA));

    WriteQueue(&tMsg);

    return 0;
}
int CallBackGGA(void *p)
{
    if (NULL == p)
    {
        return -1;
    }

    T_BDGGADATA tData;
    memset(&tData, 0x00, sizeof(tData));
    memcpy(&tData, p, sizeof(tData));

    // qDebug() << QString("GGA Lat[%1] Lon[%2]").arg(tData.fLat).arg(tData.fLon);

    T_MSG tMsg;
    tMsg.eType = E_MSGTYPE_GGA;
    tMsg.pMsg = new T_BDGGADATA;
    memset(tMsg.pMsg, 0x00, sizeof(T_BDGGADATA));
    memcpy(tMsg.pMsg, p, sizeof(T_BDGGADATA));

    WriteQueue(&tMsg);

    return 0;
}

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //! 获取串口名称
    QList<QString> portList;
    portList.clear();
    QList<QSerialPortInfo> serialPortInfo = QSerialPortInfo::availablePorts();
    for (int i=0;i<serialPortInfo.length();i++)
    {
        //    qDebug() << "Name        : " << serialPortInfo[i].portName();
        portList.append(serialPortInfo[i].portName());
    }
    ui->comboBoxSerialPort->addItems(portList);

    on_comboBoxSendCmd_activated("TCQ");
    ui->pushButtonSendCmd->setEnabled(false);
}

MainWindow::~MainWindow()
{
    Free();

    delete ui;
}

bool MainWindow::Init()
{
    //! 北斗终端标准协议编解码
    if (NULL == m_cBDPcCoder)
    {
        m_cBDPcCoder = new BDPcCoder;
        /* 初始化 */
        m_cBDPcCoder->InitCoderHeadle(E_BDUART_BDIII);

        /* 注册回调函数 */
        m_cBDPcCoder->SetDecoderCallBackFunc(&CallBackICP, E_BDPROTOCOL_ICP);
        m_cBDPcCoder->SetDecoderCallBackFunc(&CallBackTCI, E_BDPROTOCOL_TCI);
        m_cBDPcCoder->SetDecoderCallBackFunc(&CallBackGGA, E_BDPROTOCOL_GGA);
    }

    //! 初始化串口
    if (NULL == m_cSerial)
    {
        m_cSerial = new QSerialPort();
    }
    if (false == m_cSerial->isOpen())
    {
        m_cSerial->setPortName(ui->comboBoxSerialPort->currentText());          //! 串口名称
        m_cSerial->setBaudRate(ui->comboBoxRate->currentText().toLongLong());   //! 波特率
        m_cSerial->setParity(QSerialPort::NoParity);            //! 无校验
        m_cSerial->setDataBits(QSerialPort::Data8);             //! 8位数据
        m_cSerial->setStopBits(QSerialPort::OneStop);           //! 1位停止
        m_cSerial->setFlowControl(QSerialPort::NoFlowControl);  //! 无数据流控制
        if (false == m_cSerial->open(QIODevice::ReadWrite))     //! 读写模式打开
        {
            qDebug() << QString("SerialPort open fail, portname[%1] rate[%2]").arg(ui->comboBoxSerialPort->currentText()).arg(ui->comboBoxRate->currentText().toLongLong());
            return false;
        }
        qDebug() << QString("SerialPort open");

        connect(m_cSerial, &QSerialPort::readyRead, this, &MainWindow::RecvBDDataSlot, Qt::UniqueConnection);
        connect(this, &MainWindow::WriteDataSignal, this, &MainWindow::WriteDataSlot, Qt::UniqueConnection);
    }
    else
    {
        qDebug() << QString("SerialPort is open");
    }

    if (!g_cDB.open())
    {
        g_cDB = QSqlDatabase::addDatabase("QODBC");
        g_cDB.setDatabaseName(QString("DRIVER={SQL SERVER}; SERVER=%1; DATABASE=%2; UID=%3; PWD=%4")
                              .arg("59.110.112.233,2370").arg("TourPalsHelp").arg("sa").arg("LHYH@2370"));
        if (!g_cDB.open())
        {
            qDebug()<<QString::fromUtf8("打开数据库失败111");
            QSqlError error = g_cDB.lastError();
        } else {
            qDebug()<<QString::fromUtf8("打开数据库成功111");
            QSqlQuery result;

        }
    }



    if (false == g_cTime.isActive())
    {
        connect(&g_cTime, SIGNAL(timeout()), this, SLOT(ReadQueueSlot()));
        g_cTime.start(500);
    }

    return true;
}

void MainWindow::Free()
{
    if (g_cTime.isActive())
    {
        g_cTime.stop();
    }

    if (m_cSerial)
    {
        if (m_cSerial->isOpen())
        {
            m_cSerial->close();
            qDebug() << QString("SerialPort close");
        }
        else
        {
            qDebug() << QString("SerialPort is not open");
        }
        m_cSerial->deleteLater();
        m_cSerial = NULL;
    }
    else
    {
        qDebug() << QString("SerialPort is not open");
    }

    if (m_cBDPcCoder)
    {
        m_cBDPcCoder->FreeCoderHeadle();
        delete m_cBDPcCoder;
        m_cBDPcCoder = NULL;
    }
}

int MainWindow::SendICR(const T_BDICRDATA *tData)
{
    T_BDRSDATA tSendData;

    if (NULL == m_cBDPcCoder)
    {
        return -1;
    }

    if (m_cBDPcCoder->CoderICRData(tData, &tSendData))
    {
        SendBDData(tSendData);
        return 0;
    }

    return -1;
}

int MainWindow::SendMSS(const T_BDMSSDATA *tData)
{
    T_BDRSDATA tSendData;

    if (NULL == m_cBDPcCoder)
    {
        return -1;
    }

    if (m_cBDPcCoder->CoderMSSData(tData, &tSendData))
    {
        SendBDData(tSendData);
        return 0;
    }

    return -1;
}

int MainWindow::SendTCQ(const T_BDTCQDATA *tData)
{
    T_BDRSDATA tSendData;

    if (NULL == m_cBDPcCoder)
    {
        return -1;
    }

    if (false == m_cBDPcCoder->CoderTCQData(tData, &tSendData))
    {
        return -1;
    }

    if (false == SendBDData(tSendData))
    {
        return -1;
    }

    return 0;
}

int MainWindow::SendTBQ(const T_BDTBQDATA *tData)
{
    T_BDRSDATA tSendData;

    if (NULL == m_cBDPcCoder)
    {
        return -1;
    }

    if (false == m_cBDPcCoder->CoderTBQData(tData, &tSendData))
    {
        return -1;
    }

    if (false == SendBDData(tSendData))
    {
        return -1;
    }

    return 0;
}

bool MainWindow::SendBDData(const T_BDRSDATA &tData)
{
    if (m_cSerial && m_cSerial->isOpen())
    {
        emit WriteDataSignal(tData);
        return true;
    }
    else
    {
        qDebug() << QString("SerialPort is not open");
    }

    return false;
}

bool MainWindow::GetSerialPortStatus()
{
    if (NULL == m_cSerial)
    {
        return false;
    }

    return m_cSerial->isOpen();
}

void MainWindow::RecvBDDataSlot()
{
    QByteArray recvbuf;

    if (m_cSerial && m_cSerial->isOpen())
    {
        recvbuf = m_cSerial->readAll();
    }

    if (0 >= recvbuf.size())
    {
        return;
    }

    for (int i=0; i<recvbuf.size(); i++)
    {
        //! 处理BD标准协议
        if (m_cBDPcCoder)
        {
            m_cBDPcCoder->PutDataToDecoder((u1)recvbuf.at(i));
        }
    }
}

void MainWindow::WriteDataSlot(const T_BDRSDATA &tData)
{
    if (!m_cSerial)
    {
        return;
    }
    if (!m_cSerial->isOpen())
    {
        return;
    }
    if (0 >= tData.uLen)
    {
        return;
    }

    QByteArray buf(tData.sData, tData.uLen);
    m_cSerial->write(buf);
    m_cSerial->waitForBytesWritten(1000);
}

void MainWindow::checkDBSent()
{

    QSqlQuery result;
    if (result.exec("SELECT TOP 1 * FROM SMSSend_HY WHERE Status = 0 ORDER BY SubmitDateTime")) {
        while (result.next()) {
            QString text = QString("$CCTCQ,%1,2,2,1,%2,0*5B").arg(result.value(1).toString()).arg(result.value(2).toString());

            pushButtonSendCmdToDB(result.value(0).toString(), text);
        }
    } else {
        qDebug()<<"err:"<<result.lastError().text();
    }
}

void MainWindow::pushButtonSendCmdToDB(const QString &infoID, const QString &infoContent)
{
    qDebug()<<infoID;
    qDebug()<<infoContent;

    T_BDRSDATA tSendData;

    if (NULL == m_cBDPcCoder)
    {
        return ;
    }

    QString sCmd = infoContent;

    //! 计算校验
    if (sCmd.size() > 3)
    {
        sCmd.chop(3);
    }
    QByteArray arry1(sCmd.toLocal8Bit());//!  需要转fromLocal8Bit，否则校验计算不对
    if (false == m_cBDPcCoder->CoderCMDData(arry1.data(), arry1.size(), &tSendData))
    {
        return ;
    }

    //! 更新显示
    QByteArray arry2(tSendData.sData, tSendData.uLen);
    sCmd = QString::fromLocal8Bit(arry2);//!  需要转fromLocal8Bit，否则为乱码
    if (sCmd.size() > 2)
    {
        sCmd.chop(2);
    }
    ui->lineEditSendCmd->setText(sCmd);

    if (false == SendBDData(tSendData))
    {
        return ;
    }

    QSqlQuery result;
    QDateTime currentDateTime = QDateTime::currentDateTime();
    QString currentTime = currentDateTime.toString("yyyy-MM-dd hh:mm:ss");
    qDebug()<<currentTime;
    if (result.exec(QString("UPDATE [dbo].[SMSSend_HY] SET  [Status] = 1,[DisposeDateTime] = '%2'  WHERE ID = '%1'").arg(infoID).arg(currentTime))) {
        qDebug()<<QString::fromUtf8("发送数据成功222");
    } else {
        qDebug()<<QString::fromUtf8("发送数据失败222");
        qDebug()<<"err:"<<result.lastError().text();
    }

    return ;
}
int msecTimes = 4;
void MainWindow::ReadQueueSlot()
{
    // 发送检查
    if (msecTimes == 0) {
        checkDBSent();
        msecTimes = 4;
    }
    msecTimes--;

    // 接收检查
    QString sMsg;

    if (g_cQueue.isEmpty())
    {
        return ;
    }
    while(1)
    {
        g_cRWLock.lockForWrite();
        if (g_cQueue.isEmpty())
        {
            g_cRWLock.unlock();
            break;
        }
        T_MSG tMsg = g_cQueue.dequeue();
        g_cRWLock.unlock();


        switch (tMsg.eType) {
        case E_MSGTYPE_ICP:
        {
            T_BDICPDATA *tICP = (T_BDICPDATA*)tMsg.pMsg;
            ui->textBrowser->append("----------- ICP -----------");
            sMsg = QString("用户地址[%1] 通播地址[%2] 用户标识[%3] 军/民标识[%4] RDSS服务频度[%5] RDSS通信长度等级[%6] 全球短报文服务频度[%7] 全球短报文通信长度等级[%8] 下属用户数[%9]")
                    .arg(tICP->uUserID)
                    .arg(tICP->uBroadcastID)
                    .arg(tICP->eUserFlag)
                    .arg(tICP->uJMFlag)
                    .arg(tICP->uFreq)
                    .arg(tICP->uRDSSLevel)
                    .arg(tICP->uGlobalFreq)
                    .arg(tICP->uGlobalLevel)
                    .arg(tICP->uSubUserNum);
            ui->textBrowser->append(sMsg);
            delete tICP;
            tICP = NULL;
        }
            break;
        case E_MSGTYPE_TCI:
        {
            T_BDTCIDATA *tTCI = (T_BDTCIDATA*)tMsg.pMsg;
            ui->textBrowser->append("----------- TCI -----------");

            // 存入数据库接收信息表
            insertDBReceive(QString("%1").arg(tTCI->uSrcID),QString("%1").arg(tTCI->sMsg),QString("%1:%2:%3").arg(tTCI->uHour).arg(tTCI->uMin).arg(tTCI->uSec));

            sMsg = QString("发信方ID[%1] 收信方ID[%2] 频点[%3] 时间[%4:%5:%6] 编码类型[%7] 通信数据[%8]")
                    .arg(tTCI->uSrcID)
                    .arg(tTCI->uDestID)
                    .arg(tTCI->uFreq)
                    .arg(tTCI->uHour)
                    .arg(tTCI->uMin)
                    .arg(tTCI->uSec)
                    .arg(tTCI->eCoding)
                    .arg(tTCI->sMsg);
            ui->textBrowser->append(sMsg);
            delete tTCI;
            tTCI = NULL;
        }
            break;
        case E_MSGTYPE_GGA:
        {
            T_BDGGADATA *tGGA = (T_BDGGADATA*)tMsg.pMsg;
            ui->textBrowser->append("----------- GGA -----------");
            sMsg = QString("时间[%1:%2:%3.%4] 纬度方向[%5] 纬度[%6] 经度方向[%7] 经度[%8] 高程[%9]")
                    .arg(tGGA->uHour)
                    .arg(tGGA->uMin)
                    .arg(tGGA->uSec)
                    .arg(tGGA->u001Sec)
                    .arg(tGGA->uLatPath)
                    .arg(tGGA->fLat)
                    .arg(tGGA->uLonPath)
                    .arg(tGGA->fLon)
                    .arg(tGGA->fHeight);
            ui->textBrowser->append(sMsg);
            delete tGGA;
            tGGA = NULL;
        }
            break;
        default:
            break;
        }
    }
}

void MainWindow::insertDBReceive(const QString &userID, const QString &content, const QString &time)
{

    QSqlQuery result;
    // if (result.exec(QString::fromUtf8("INSERT INTO [dbo].[SMSReceive_HY] VALUES ('%1' ,'%2', '%3')").arg(userID).arg(content).arg(time))) {
    if (result.exec(QString::fromUtf8("EXEC HY_SaveInfo '%1' ,'%2', '%3'").arg(userID).arg(content).arg(time))) {

        qDebug()<<QString::fromUtf8("接收数据插入成功333");
    } else {
        qDebug()<<QString::fromUtf8("接收数据插入失败333");
        qDebug()<<"err:"<<result.lastError().text();
    }
}

void MainWindow::on_pushButtonSeriportOpen_clicked()
{
    if (true == GetSerialPortStatus())
    {
        Free();
    }
    else
    {
        Init();
    }

    if (true == GetSerialPortStatus())
    {
        ui->pushButtonSeriportOpen->setText(tr("关闭"));
        ui->pushButtonSendCmd->setEnabled(true); //! 发送按钮可用
    }
    else
    {
        ui->pushButtonSeriportOpen->setText(tr("打开"));
        ui->pushButtonSendCmd->setEnabled(false); //! 发送按钮不可用
    }
}

void MainWindow::on_comboBoxSendCmd_activated(const QString &arg1)
{
    if (0 == arg1.compare("TCQ"))
    {
        ui->lineEditSendCmd->setText("$CCTCQ,1860269,2,2,1,北斗通信汉字电文,0*5B");
    }
    else if (0 == arg1.compare("MSS"))
    {
        ui->lineEditSendCmd->setText("$CCMSS,Z,5,S2C,,B2b,,B3I,,,,,,,*2A");
    }
    else
    {
        ui->lineEditSendCmd->setText("");
    }
}

void MainWindow::on_pushButtonSendCmd_clicked()
{
    T_BDRSDATA tSendData;

    if (NULL == m_cBDPcCoder)
    {
        return ;
    }

    //! 计算校验
    QString sCmd = ui->lineEditSendCmd->text();
    QStringList listCmd = sCmd.split(",");
    if (sCmd.size() > 3)
    {
        sCmd.chop(3);
    }
    QByteArray arry1(sCmd.toLocal8Bit());//!  需要转fromLocal8Bit，否则校验计算不对
    if (false == m_cBDPcCoder->CoderCMDData(arry1.data(), arry1.size(), &tSendData))
    {
        return ;
    }

    //! 更新显示
    QByteArray arry2(tSendData.sData, tSendData.uLen);
    sCmd = QString::fromLocal8Bit(arry2);//!  需要转fromLocal8Bit，否则为乱码
    if (sCmd.size() > 2)
    {
        sCmd.chop(2);
    }
    ui->lineEditSendCmd->setText(sCmd);

    if (false == SendBDData(tSendData))
    {
        return ;
    }


    QDateTime currentDateTime = QDateTime::currentDateTime();
    QString currentTime = currentDateTime.toString("yyyy-MM-dd hh:mm:ss");
    QSqlQuery result;
    if (result.exec(QString::fromUtf8("INSERT INTO [dbo].[SMSSend_HY] VALUES ('%1' ,'%2', '',2,'%3')").arg(listCmd[1]).arg(listCmd[5]).arg(currentTime))) {
        qDebug()<<QString::fromUtf8("发送数据成功444");
    } else {
        qDebug()<<QString::fromUtf8("发送数据失败444");
        qDebug()<<"err:"<<result.lastError().text();
    }
    return ;
}

//! \brief GlobalTools::QStringToChar Qstring转char
//! \param src 转换前的QString
//! \param dest转换后的char
//! \return void
void MainWindow::QStringToChar(QString src, char *dest)
{
    char *buf = NULL;

    if (src.isEmpty())
    {
        return;
    }

    std::string str = src.toStdString();
    buf = new char[str.size()+1];
    //! 使用 src.toLatin1().data()也能转char
    memset(buf, 0x00, str.size()+1);
    strcpy(buf, str.c_str());

    if (dest)
    {
        strcpy(dest, buf);
    }

    delete []buf;
    buf = NULL;
}
